import Header from "./components/Header";
import List from "./components/List";
import Footer from "./components/Footer";
import './App.css'
import { useState } from "react";
import { useEffect } from "react";
import context from './context'

/* 
应用组件
*/
export default function App() {
  /* 
  [
    {id: 1, title: '吃饭', complete: false},
    {id: 2, title: '睡觉', complete: true},
    {id: 3, title: '打代码', complete: false},
  ]
  */
  // 定义todos状态
  /* 
  初始时, 读取保存的todos并解析为js的数组, 作为todos的初始值
  当没时, todos的初始值应该为[]
  */
  const [todos, setTodos] = useState(JSON.parse(localStorage.getItem('todos_key')) || [])

  /* 
  只要todos变化了, 就会将最新的todos保存到local中
  */
  useEffect(() => { // didMount + didUpdate (todos)
    localStorage.setItem('todos_key', JSON.stringify(todos))
  }, [todos])  // 监视了todos


  /* 
  添加todo
  Header传过来什么数据?  title
  */
  const addTodo = (title) => {
    // 根据title创建一个新的todo
    const todo = {id: Date.now(), title, complete: false}
    // 添加到todos
    // 更新todos
    // 问题: 调用setXxx方法更新state时, 不能直接指定原数据, 即使内部数据发生了变化 => 界面不会更新
    // 需要指定一个新的值
    // setTodos(todos) // 传递进去的是一个新的todos吗?  不是, 是同一个, 只是内部多一个todo
    // 需要一个包含todos中所有数据的新数组
    // todos.unshift(todo)
    // console.log('addTodo', todos)
    // setTodos([...todos])
    setTodos([todo, ...todos])

    // todos.unshift(todo)
    // setTodos(todos)  // 组件不会重新调用渲染   内部会进行===的比较, 如果相同不更新
  }

  /* 
  删除指定id对应的todo
  */
  function deleteTodo(id) {
    // 产生一个去除指定id对应的todo的新todos
    const newTodos = todos.filter(todo => todo.id!==id)
    // 更新todos
    setTodos(newTodos)

    // setTodos(todos.filter(todo => todo.id!==id))
  }

  /* 
  反选指定todo: 切换指定todo的complete值
  */
  const toggleTodo = (todo) => {
    // 切换指定todo的complete值
    todo.complete = !todo.complete // 修改的是todos内部的某个todo内部的属性
    // 更新todos
    setTodos([...todos])
  }

  /* 
  清除已完成的todo
  */
  const clearCompleteTodos = () => {
    setTodos(todos.filter(todo => !todo.complete))
  }

  /* 
  全选/全不选
  */
  const selectAll = (isCheck) => {
    // 将每个todo的complete变为isCheck
    todos.forEach(todo => todo.complete = isCheck)
    setTodos([...todos])
  }
  


  return (
    <div className="todo-container">
    <div className="todo-wrap">
      <Header addTodo={addTodo}/>
      {/* 将要传递给后代组件的数据, 通过value属性传递给Provider */}
      <context.Provider value={{todos, deleteTodo, toggleTodo}}>
        <List />
      </context.Provider>
      
      <Footer todos={todos} clearCompleteTodos={clearCompleteTodos} selectAll={selectAll}/>
    </div>
  </div>
  )
}
